home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-20
/
rs0422.zip
/
LEVEL3
/
BUFFER.C
next >
Wrap
C/C++ Source or Header
|
1990-01-30
|
10KB
|
391 lines
/*
* Copyright 1988 by the Radio Amateur Telecommunications Society
* and Thomas A. Moulton, W2VY
*
* This software may only be modified, copied, distributed or
* executed for non-profit purposes by individuals operating
* systems in the Amateur Radio Service. Credit to the
* author(s) and to the Radio Amateur Telecommunications Society
* must be made in modules where RATS provided software is used,
* and in any announcements and documentation.
*
* As a non-profit, research and development organization, the
* Radio Amateur Telecommunications Society distributes software
* in both executable and source forms. This policy is in place
* to encourage the development and distribution of OSI-based,
* networking tools. In order to protect the interests of the
* Society and the authors, we have placed some conditions
* of use on the software. Other groups are encouraged
* to place the same or similar guidelines on
* software they produce.
*
* The Radio Amateur Telecommunications Society reserves the right
* to specify and alter the terms under which software provided by
* the Society may be used. This policy is consistent with the
* objective of uniform and consistent "Open Systems Interconnections."
*
* All acceptable Amateur Radio related uses of this software
* will be outlined in the "ROSE Implementer's Guide". Individuals
* or organizations wishing to add to, or modify the provisions of
* the guide to accommodate local or evolutionary requirements
* should document the proposed change(s) and forward them to the
* Society. If accepted, written notification will be provided by
* the Society to the submitting organization or individual(s).
* The Society will then issue a "ROSE Implementer's Guide Change
* Notice". Periodically, the Society will re-issue the "ROSE
* Implementer's Guide" and incorporate the text of the change
* notices. This procedure has been put in to place to ensure
* compatibility between systems and to ensure their "Openness"
* and interoperability.
*
* No part of this software may be used in other packages
* without prior authorization from the author or the Society.
* Software incorporating this module, all or in part, must be
* provided to the Society prior to distribution or use by
* anyone not directly involved in testing of the revised
* environment. Current releases of the combined software must
* be provided to the Society in both source and executable
* forms. Adequate documention to produce an executable module
* from the provided source must also be included.
*
* Non-Amateur Radio non-profit uses may be authorized on a case
* by case basis. Inquiries for such use may be made in writing
* to the Society. Non-commercial uses consistent with the
* general principles of Open Systems Interconnection Reference
* Model will be generally considered with favor.
*
* Commercial licensing of the software is also available based
* on normal commercial terms. Licensing inquiries should be
* directed to the Society. Commercial licensing of the standard
* software will be done in situations which materially benefit
* the Amateur Radio Packet Network. Additional licensing is
* reserved by the individual authors.
*
* The Radio Amateur Telecommunications Society provides this software
* on an "as is" basis. The Society assumes no liability for
* loss incurred through the use of this software. Amateur Radio
* use of this software implies non-commercial and voluntary
* development, deployment and use of this software in a "Amateur",
* non-commercial service. Commercial users are encouraged to
* inspect their copies of the source code. Source code modification
* licenses are available if a combined Object and Source Code
* license was not originally established.
*
* The Society may be contacted by writing or calling at:
*
* The Radio Amateur Telecommunications Society
* 206 North Vivyen Street.
* Bergenfield, New Jersey 07621
*
* Telephone: 201-387-8896
*
*/
/* buffer.c */
/* This file contains the buffer access routines
Buffer get next char
bgetch(datastr) : integer, char or -1 if EOF
Buffer append ch
bappch(datastr,ch)
buflen(datastr) Return length of packet
binsert(datastr1, datastr2) Insert buf1 before buf2
dup_pkt(datastr) : datastr dup buffer headers, same data
*/
#define buftst 0
#if buftst
#define BUFCHK(a) buf_chk(a)
#else
#define BUFCHK
#endif
/* This is also in assembly in LEVEL1.AS, the C version is being used now */
int bgetch(b)
struct datastr **b;
{
register struct datastr *b1;
struct datastr *b2; /* Needs to be re-entrant */
if ((b1 = *b) == (struct datastr *)NULL) return EOF;
while ( (b1->rdata == b1->wdata) /* This segment is empty, try next */
|| (b1->rdata > b1->max) ) /* Hit eof for this one */ {
b2 = b1;
b1 = b1->nexts; /* Get next segment */
free(b2); /* Free old */
if (b1 == (struct datastr *)NULL) /* Hit EOF, no data */ {
*b=(struct datastr *)NULL;
return EOF;
}
}
*b=b1;
return ((int)*b1->rdata++);
}
int bappch(b, ch)
register struct datastr *b;
unsigned char ch; /* Needs to be re-entrant */
{
while (b->nexts) b=b->nexts;
if (b->wdata > b->max) return EOF;
*b->wdata++ = ch;
if (b->wdata > b->max) return 1;
return 0;
}
int buflen(b1)
register struct datastr *b1;
{
static int cnt;
cnt=0;
BUFCHK(b1);
while (b1 != (struct datastr *)NULL) {
cnt += (b1->wdata - b1->rdata);
b1 = b1->nexts;
}
return cnt;
}
struct datastr *
binsert(b1,b2)
struct datastr *b1, *b2;
{
static struct datastr *bo, *bn;
register struct datastr *b;
bo=b2; /* Old root of the packet */
b=bn=b1; /* New root, ie. bufs to insert */
BUFCHK(bo);
BUFCHK(bn);
if (bo == (struct datastr *)NULL) return bn;
if (bn == (struct datastr *)NULL) return bo;
while (b->nexts != NULL) b= b->nexts;
b->nexts=bo;
bo->next=NULL;
return bn;
}
#if 0
struct datastr *
dup_pkt(b)
register struct datastr *b;
{
static struct datastr *p1;
static unsigned char *c;
if (b == (struct datastr *)NULL) return b;
if ((p1=new_buffer(buflen(b))) == NULL) return p1;
do {
for (c=b->rdata;c<b->wdata;c++) bappch(p1,*c);
b=b->nexts;
} while (b);
return p1;
}
#else
struct datastr *
dup_pkt(b1)
struct datastr *b1;
{
static struct datastr *pkt, *p, *b;
register struct datastr *p1;
b=b1;
BUFCHK(b);
pkt=new_buffer(0);
if (pkt == (struct datastr *)NULL) return NULL;
/* pkt->next=pkt->nexts=NULL; Done in New_buffer() */
pkt->rdata = b->rdata;
pkt->wdata = b->wdata;
pkt->max = b->max;
p=pkt;
while (b != (struct datastr *)NULL) {
if (b=b->nexts) /* Copy pointers */ {
p1=new_buffer(0);
if (p1 == (struct datastr *)NULL) /* No memory, free pkt and fail */ {
free_pkt(pkt);
return (struct datastr *)NULL;
}
p->nexts=p1;
p1->rdata=b->rdata;
p1->wdata=b->wdata;
p1->max = b->max;
p=p1;
}
}
return pkt;
}
#endif
void
free_pktx(p)
struct datastr **p;
{
register struct datastr *b;
if (p) {
if (b = *p) {
free_pktx(&b->nexts);
free(b);
*p = NULL;
}
}
}
free_queue(q)
struct datastr **q;
{
register struct datastr *b;
if (q) {
if (b = *q) {
free_queue(&b->next);
free_pktx(q);
}
}
}
#if 0
struct datastr *
frag_pkt(px,size) /* returns a NULL terminated queue of packets */
struct datastr *px;
int size;
{
static struct datastr *p, *p1, *p2, *pr;
static int i;
p=px;
p->next=NULL;
if (buflen(p) <= size) return p;
pr=p;
p1=NULL;
while (buflen(p) > size) {
if ((p2=new_buffer(size)) == NULL) break;
for (i=0;i<size;i++) bappch(p2,bgetch(&p));
if (!p1) pr=p2;
if (p1) p1->next=p2;
p1=p2;
}
if (p && p1) p1->next=p;
return pr;
}
#else
struct datastr *
frag_pkt(px,siz) /* returns a NULL terminated queue of packets */
struct datastr *px;
int siz;
{
static struct datastr *p, *pk, *pks;
register struct datastr *pkr;
static int size, len, i;
pkr=px;
pkr->next=NULL;
BUFCHK(pkr);
size=siz;
if (buflen(pkr) <= size) return pkr;
len=0;
p=pk=pks=NULL;
while (pkr) /* There is more to process */ {
i=pkr->wdata - pkr->rdata;
puthex2("frag",len,"",i);
if (i+len <= size) /* Move the segment over */ {
if (!pks) /* Start of packet */ {
if (pk) pk->next=pkr;
pk=pkr;
if (!p) p=pkr; /* Return value, first packet */
}
else /* Just add to end of segment queue */ {
pks->nexts=pkr;
}
pks=pkr; /* Current Seg */
pkr=pkr->nexts; /* Advance to next seg */
pks->nexts=NULL;
len += i;
}
else /* Split Segment */ {
if (!pks) /* Start of a packet */ {
pks=new_buffer(0);
if (pk) pk->next=pks;
pk=pks;
if (!p) p=pk;
}
else {
pks->nexts=new_buffer(0);
pks=pks->nexts;
}
pks->rdata=pkr->rdata;
pks->wdata=pkr->rdata + size-len;
pks->max=pks->wdata -1;
pkr->rdata += size-len;
len=size;
}
if (len == size) {
pks=NULL; /* Start a new packet */
len=0;
}
}
BUFCHK(p);
return p;
}
#endif
struct datastr *
mkpkt(s)
register char *s;
{
static struct datastr *p;
int strlen();
p=new_buffer(strlen(s)+30); /* Room for message and some spare */
if (p) while (*s) bappch(p,(*s++));
BUFCHK(p);
return p;
}
#if buftst
int is_ROM(i)
int i;
{
return (i>0);
}
buf_chk(p)
struct datastr *p;
{
struct datastr *p1;
while (p) {
if (is_ROM(p) || is_ROM(p->nexts) || is_ROM(p->next) ||
!p->rdata || !p->wdata || !p->max) restart();
p1=p->nexts;
while (p1) {
if (is_ROM(p1) ||!p->rdata || !p->wdata
|| !p->max) restart();
p1=p1->nexts;
}
p=p->next;
}
}
#endif
struct datastr *
bappstr(bp, str)
struct datastr *bp;
register char *str;
{
if (bp) {
while (*str) {
if (bappch(bp, *str) != -1) str++;
else return (binsert(bp,mkpkt(str)));
}
}
return bp;
}